import topoFile from "@/assets/LHCONE";
import G6 from "@antv/g6";
import { useCallback, useEffect, useState } from "react";
import { Requirement } from "./interfaces";


export default () => {
  const [loading, setLoading] = useState(true);
  const [routers, setRouters] = useState({});
  const [hosts, setHosts] = useState({});
  const [topo, setTopo] = useState({});
  const [path, setPath] = useState([]);
  const [requirements, setRequirements] = useState<Requirement[]>([])
  const { findShortestPath } = G6.Algorithm;

  const addRequirement = (req: Requirement) => {
    req.id = Math.random().toString();
    setRequirements([...requirements, req])
  }

  const computePath = useCallback(
    (src, dst) => {
      const { length, path, allPath } = findShortestPath(topo, src, dst);
      setPath(path);
    },
    [topo]
  );

  useEffect(() => {
    setTopo({
      nodes: [...topoFile.routers, ...topoFile.hosts],
      edges: topoFile.links,
    });

    setHosts(
      Object.fromEntries(
        topoFile.hosts.map((host, index) => [
          host.id,
          {
            ...host,
            ip: "10.0." + index + ".1",
            prefixLength: 24,
          },
        ])
      )
    );
  }, []);

  useEffect(() => {
    setRouters(
      Object.fromEntries(
        topoFile.routers.map((router, index) => {
          const fib = Object.values(hosts)
            .map((host) => {
              const { length, path, allPath } = findShortestPath(
                topo,
                router.id,
                host.id
              );
              // TODO: check no path, return null and filter
              return {
                prefix: host.ip + "/" + host.prefixLength,
                nexthop: path[1],
              };
            })
            .filter((item) => item != null);
          return [
            router.id,
            {
              ...router,
              fib: fib,
            },
          ];
        })
      )
    );
    console.log(routers)
    setLoading(false);
  }, [hosts]);

  const query = useCallback(
    (src: string, dip) => {
      if (undefined == hosts[src] && undefined == routers[src]) {
        return "Error: The source node does not exist.";
      }
      let dst = Object.values(hosts).filter((host) => host.ip == dip);
      if (dst.length == 0) {
        let res = {
          path: [src, 'DROP'],
          throughput: 0,
          delay: 0,
        };
        return JSON.stringify(res, null, 2);
      } else {
        const { length, path, allPath } = findShortestPath(
          topo,
          src,
          dst[0].id
        );
        let res = {
          path: path,
          throughput: 1000,
          delay: 20,
        };
        if (length == 0) {
          res = {
            path: [src],
            throughput: 0,
            delay: 0,
          };
        }

        return JSON.stringify(res, null, 2);
      }
    },
    [hosts, routers, topo]
  );

  return { topo, hosts, routers, loading, path, computePath, query, requirements, addRequirement,setRequirements };
};
